#ifndef __GAMELAYERCONFIGFILELOADERDAT_H__
#define __GAMELAYERCONFIGFILELOADERDAT_H__

#include "GameLayerConfig.h"

namespace LoadFileDat
{

	enum EGameLayerConfigElemType
	{
		EGLET_LAYER,
		EGLET_BUTTON,
		EGLET_SPRITE,
	};

	struct SGLConfigFileHead
	{
		bool Read(FILE* fp)
		{
			fread(this,sizeof(SGLConfigFileHead),1,fp);
			return true;
		}
		int TotalLayerCount;
	};

	struct SGLConfigElem
	{
		float Width;
		float Height;
		float PosX;
		float PosY;
		int ZOrder;
		bool XT;
		bool YT;
		int NameLen;
	};

	struct SGLConfigButton : SGLConfigElem
	{
		int NormalImageLen;
		int mSelectedImageLen;
		int mDisabledImageLen;
		int TextLen;
		int FontLen;
		int FontSize;
		GameLayerConfigButton* Load(FILE* fp)
		{
			GameLayerConfigButton* ret = new GameLayerConfigButton();
			char strbuffer[128];
			fread(this,sizeof(SGLConfigButton),1,fp);
			fread(strbuffer,sizeof(char),NameLen,fp);
			ret->mName = strbuffer;
			ret->mWidth = Width;
			ret->mHeight = Height;
			ret->mPosX = PosX;
			ret->mPosY = PosY;
			ret->mZOrder = ZOrder;
			ret->mXT = XT;
			ret->mYT = YT;

			fread(strbuffer,sizeof(char),NormalImageLen,fp);
			ret->mNormalImage = strbuffer;
			fread(strbuffer,sizeof(char),mSelectedImageLen,fp);
			ret->mSelectedImage = strbuffer;
			fread(strbuffer,sizeof(char),mDisabledImageLen,fp);
			ret->mDisabledImage = strbuffer;
			fread(strbuffer,sizeof(char),TextLen,fp);
			ret->mText = strbuffer;
			fread(strbuffer,sizeof(char),FontLen,fp);
			ret->mFont = strbuffer;
			ret->mFontSize=FontSize;
			return ret;
		}
	};

	struct SGLConfigSprite : SGLConfigElem
	{
		GameLayerConfigSprite* Load(FILE* fp)
		{
			GameLayerConfigSprite* ret = new GameLayerConfigSprite();
			char strbuffer[128];
			fread(this,sizeof(SGLConfigSprite),1,fp);
			fread(strbuffer,sizeof(char),NameLen,fp);
			ret->mName = strbuffer;
			ret->mWidth = Width;
			ret->mHeight = Height;
			ret->mPosX = PosX;
			ret->mPosY = PosY;
			ret->mZOrder = ZOrder;
			ret->mXT = XT;
			ret->mYT = YT;
			return ret;
		}
	};



#define REGIST_LOADCONFIG(type,loadclass) case type:\
	{\
	loadclass loadelem;\
	Elem = (GameLayerConfigElem*)loadelem.Load(fp);\
	}\
	break;

	struct SGLConfigGameLayer : SGLConfigElem
	{
		int ElemNum;

		GameLayerConfigLayer* Load(FILE* fp)
		{
			GameLayerConfigLayer* ret = new GameLayerConfigLayer();
			char strbuffer[128];
			fread(this,sizeof(SGLConfigGameLayer),1,fp);
			fread(strbuffer,sizeof(char),NameLen,fp);
			ret->mName = strbuffer;
			ret->mWidth = Width;
			ret->mHeight = Height;
			ret->mPosX = PosX;
			ret->mPosY = PosY;
			ret->mZOrder = ZOrder;
			ret->mXT = XT;
			ret->mYT = YT;
			for(int i=0;i<ElemNum;i++)
			{
				int blocksize;
				EGameLayerConfigElemType type;
				GameLayerConfigElem* Elem = 0;
				long fppos = ftell(fp);
				fread(&blocksize,sizeof(int),1,fp);
				fread(&type,sizeof(EGameLayerConfigElemType),1,fp);
				switch(type)
				{
					REGIST_LOADCONFIG(EGLET_LAYER,SGLConfigGameLayer);
					REGIST_LOADCONFIG(EGLET_BUTTON,SGLConfigButton);
					REGIST_LOADCONFIG(EGLET_SPRITE,SGLConfigSprite);
				default:
					{
						return 0;
					}
					break;
				}
				if(Elem)
					ret->mSubElemLst.PushBack(Elem);
				else
					fseek(fp,SEEK_SET,fppos+blocksize);
			}
			return ret;
		}
	};


	class GameLayerConfigFileLoaderDat 
		:public GameLayerConfigFileLoader
	{
	public:
		virtual void LoadFile(CSString str,CSHashMap<CSString,GameLayerConfigLayer*>& map)
		{
			FILE* fp = fopen(str.GetBuffer(),"rb");
			if(!fp)
				return ;
			SGLConfigFileHead filehead;
			filehead.Read(fp);

			for(int i=0;i<filehead.TotalLayerCount;i++)
			{
				int blocksize;
				EGameLayerConfigElemType type;
				long fppos=ftell(fp);
				fread(&type,sizeof(EGameLayerConfigElemType),1,fp);
				fread(&blocksize,sizeof(int),1,fp);
				if(type!=EGLET_LAYER)
				{
					fseek(fp,SEEK_SET,fppos+blocksize);
					continue;
				}
				SGLConfigGameLayer gamelayer;
				GameLayerConfigLayer* layer = gamelayer.Load(fp);
				if(!layer)
				{
					fseek(fp,SEEK_SET,fppos+blocksize);
					break;
				}
				map.Insert(layer->mName,layer);
			}
			fclose(fp);
		}
	};

}
#endif
